// file:system/fs/kernelif.c
// autor:jiangxinpeng
// time:2021.6.30
// copyright:(C) 2020-2050 by jiangxinpeng,All right are reserved.

#include <os/fs.h>
#include <os/fsal.h>
#include <os/debug.h>
#include <os/task.h>
#include <os/schedule.h>
#include <os/fd.h>
#include <os/kernelif.h>
#include <lib/errno.h>
#include <sys/status.h>

int KFileOpen(const char *path, int flags)
{
    int handle;
    int fd = -1;

    if (!path)
        return -EINVAL;
    handle = fsif.open(path, flags);
    if (handle < 0)
    {
        KPrint("[fs] open file failed\n");
        return -1;
    }
    fd = FsFdInstall(handle, FILE_FD_KERNEL);
    return fd;
}

int KFileClose(int fd)
{
    file_fd_t *ffd = FdToFile(fd);
    if (!ffd || ffd->handle < 0 || !ffd->fsal)
        return -EINVAL;
    if (!ffd->fsal->close)
        return -ENOSYS;
    if (ffd->fsal->close(ffd->handle) < 0)
        return -1;
    return FsFdUnInstall(fd);
}

int KFileRead(int fd, void *buffer, size_t bytes)
{
    file_fd_t *ffd = FdToFile(fd);

    if (fd < 0 || !ffd || ffd->handle < 0 || !ffd->fsal)
        return -EINVAL;
    if (!ffd->fsal->read)
        return -ENOSYS;
    return ffd->fsal->read(ffd->handle, buffer, bytes);
}

int KFileWrite(int fd, void *buffer, size_t bytes)
{
    file_fd_t *ffd = FdToFile(fd);

    if (fd < 0 || !ffd || ffd->handle < 0 || !ffd->fsal)
        return -EINVAL;
    if (!ffd->fsal->write)
        return -ENOSYS;
    return ffd->fsal->write(ffd->handle, buffer, bytes);
}

int KFileStatus(const char *path, status_t *buff)
{
    if (!path || !buff)
        return -EINVAL;
    return fsif.status(path, buff);
}

int KFileAccess(const char *path, int mode)
{
    if (!path)
        return -EINVAL;
    if (!fsif.access)
        return -ENOSYS;
    return fsif.access(path, mode);
}

int KFileFTell(int fd)
{
    file_fd_t *ffd = FdToFile(fd);
    if (fd < 0 || !ffd || ffd->handle < 0 || !ffd->fsal)
        return -EINVAL;
    if (!ffd->fsal->ftell)
        return -ENOSYS;
    return ffd->fsal->ftell(ffd->handle);
}

int KFileLSeek(int fd, offset_t off, int where)
{
    file_fd_t *ffd = FdToFile(fd);
    if (!ffd || ffd->handle < 0 || !ffd->fsal)
        return -EINVAL;
    if (!ffd->fsal->lseek)
        return -ENOSYS;
    return ffd->fsal->lseek(ffd->handle, off, where);
}

int KFileMkDir(const char *path, mode_t mode)
{
    if (!path)
        return -EINVAL;
    return fsif.mkdir(path, mode);
}

int KFileRmDir(const char *path)
{
    if (!path)
        return -EINVAL;
    return fsif.rmdir(path);
}

int KFileReName(const char *path_old, const char *path_new)
{
    if (!path_old || !path_new)
        return -EINVAL;
    return fsif.rename(path_old, path_new);
}

int KfileMkFs(const char *dev, char *fstype, int flags)
{
    if (!dev || !fstype)
        return -EINVAL;
    return fsif.mkfs(dev, fstype, flags);
}

int KFileMount(const char *src, const char *targe, char *fstype, int flags)
{
    if (!src || !targe || !fstype)
        return -EINVAL;
    return fsif.mount(src, targe, fstype, flags);
}

int KFileUnMount(const char *src)
{
    if (!src)
        return -EINVAL;
    return fsif.unmount(src);
}

int KFileUnlink(const char *path)
{
    if (!path)
        return -EINVAL;
    return fsif.unlink(path);
}

int KFileReadDir(int dir, char *buff)
{
    if (!buff)
        return -EINVAL;
    return fsif.readdir(dir, (dirent_t *)buff);
}

int KFileOpenDir(const char *path)
{
    if (!path)
        return -EINVAL;
    return fsif.opendir(path);
}

int KFileCloseDir(int dir)
{
    if (dir < 0)
    {
        return -EINVAL;
    }
    return fsif.closedir(dir);
}

int KFileRewind(int fd)
{
    file_fd_t *ffd = FdToFile(fd);
    if (!ffd || ffd->handle < -1 || !(ffd->fsal))
        return -EINVAL;
    if (!(ffd->fsal->rewind))
        return -ENOSYS;
    return ffd->fsal->rewind(ffd->handle);
}

int KFileRewindDir(int dir)
{
    if (dir < 0)
        return -EINVAL;

    return fsif.rewinddir(dir);
}

int KFileGetCWD(char *path, uint64_t len)
{
    if (!path)
        return -EINVAL;
    task_t *cur = cur_task;
    if (!cur)
        return -EINVAL;
    if (!cur->fileman)
        return -EINVAL;
    memcpy(path, cur->fileman->cwd, min(len, sizeof(cur->fileman->cwd)));
}